import json,re
from jsonpath_ng import parse
from config.all_paths import config_variable_path
from config.global_variable import GLOBAL_VALS
from utils.file_handling.txt_handling import write_txt


def extract_key_value(json_data, key_to_extract):
    """
    提取返回值JSON中指定key的值
    :param json_data: JSON数据，字符串格式
    :param key_to_extract: 要提取的key的路径，使用jsonpath语法
    :return: 提取的值，如果找不到则返回None
    """
    # 将JSON数据解析为Python字典
    data = json.loads(json_data)

    # 使用jsonpath解析器解析JSON数据
    jsonpath_expr = parse(key_to_extract)

    # 应用解析器到数据上，并获取匹配的结果
    matches = [match.value for match in jsonpath_expr.find(data)]

    # 如果有匹配的结果，则返回第一个结果，否则返回None
    return matches[0] if matches else None



# def extract_and_store_values(api_response, field_info_list):
#     for field_info in field_info_list:
#         if field_info and isinstance(field_info, dict):
#             for key, value in field_info.items():
#                 extracted_value = jsonpath.jsonpath(api_response, value)  # 使用 JSONPath 提取值
#                 if extracted_value:  # 如果提取到值
#                     GLOBAL_VALS[key] = extracted_value[0]  # 存入global_val字典中


def extract_and_store_values(api_response, field_info_list):
    '''
    存储提取到的值
    :param api_response:接口返回值
    :param field_info_list: 字典列表[{},{}]
    :return:
    '''
    for field_info in field_info_list:
        if field_info and isinstance(field_info, dict):
            for key, value in field_info.items():
                # value 使用$.a.b.c这种格式，即路径
                # 使用jsonpath解析器解析JSON数据
                jsonpath_expr = parse(value)
                # 应用解析器到数据上，并获取匹配的结果
                matches = [match.value for match in jsonpath_expr.find(api_response)]
                # print(matches[0])
                if matches:
                    GLOBAL_VALS[key] = matches[0]
                else:
                    GLOBAL_VALS[key] = '未获取到值'


## 替换在这里完成
def substitution_variables(request_data):
    # 替换请求数据
    for key, value in request_data.items():
        if isinstance(value, str) and '$' in value:  # 如果值是字符串且包含$
            global_val_key = value[1:]  # 获取$后面的key
            if global_val_key in GLOBAL_VALS:  # 如果全局变量中有对应的值
                request_data[key] = GLOBAL_VALS[global_val_key]  # 替换值
        elif isinstance(value, dict):  # 如果值是字典
            substitution_variables(value)  # 递归地调用substitution_variables函数
        elif isinstance(value, list):  # 如果值是列表
            for i, item in enumerate(value):
                if isinstance(item, (dict, list)):  # 如果列表中的元素是字典或列表
                    substitution_variables(item)  # 递归地调用substitution_variables函数
    return request_data  # 返回更新后的数据


def substitution_url(request_url):
    if '$' in request_url:
        # 获取对应的值
        variables = re.findall(r'\$\w+', request_url)
        for variable in variables:
            key = variable[1:]  # 去掉 $ 符号
            if key in GLOBAL_VALS:
                new_value = str(GLOBAL_VALS[key])  # 将值转换为字符串
                request_url = request_url.replace(variable, new_value)
    return request_url


# ++++++++++++
def get_value_from_json(key, tdict, tem_list):
    """
    从Json中获取key值:
    新建两个函数A和B，函数 A处理字典数据，被调用后，判断传递的参数，如果参数为字典，则调用自身；
    如果是列表或者元组，则调用列表处理函数B；
    函数 B处理列表，被调用后，判断传递的参数，如果参数为列表或者元组，则调用自身；
    如果是字典，则调用字典处理函数A；
    :param key:
    :param tdict:
    :param tem_list:[]
    :return:
    """
    if not isinstance(tdict, dict):
        return tdict, "is not dict"
    elif key in tdict.keys():
        tem_list.append(tdict[key])
    else:
        for value in tdict.values():
            if isinstance(value, dict):
                get_value_from_json(key, value, tem_list)
            elif isinstance(value, (list, tuple)):
                _get_value(key, value, tem_list)
    return tem_list


def _get_value(key, tdict, tem_list):
    """
    :param key:
    :param tdict:
    :param tem_list:
    :return:
    """
    for value in tdict:
        if isinstance(value, (list, tuple)):
            _get_value(key, value, tem_list)
        elif isinstance(value, dict):
            get_value_from_json(key, value, tem_list)


def set_global(set_global_vars, response_json):
    '''
    抽取接口返回的值存储到全局变量字典中
    [{'name':'query'},{'name2':'query2'}]
    :param set_global_vars: 设置的需要抽取值的名称，以及在接口中查询该值的语句
    :param response_json: 接口返回值
    :return:
    '''
    if set_global_vars and isinstance(set_global_vars, list):
        for set_global_var in set_global_vars:
            if isinstance(set_global_var, dict):
                name = list(set_global_var.keys())[0]
                query = list(set_global_var.values())[0]
                value = dict_get(response_json, query)
                if value is None or value == '':
                    continue
                else:
                    GLOBAL_VALS[name] = value
                    # 将最新的global写入txt文件
                    write_txt(config_variable_path, str(GLOBAL_VALS))
    if set_global_vars and isinstance(set_global_vars, dict):
        for key, value in set_global_vars.items():
            GLOBAL_VALS[key] = value
            write_txt(config_variable_path, str(GLOBAL_VALS))


def dict_get(dic, locators, default=None):
    '''
    获取多层嵌套的字典中的某个值（接口响应数据一般都是多层嵌套的字典）
    :param dic: 输入需要在其中取值的原始字典 <dict>,即接口响应数据
    :param locators: 输入取值定位器, 如:['result', 'msg', '-1', 'status'] <list>
    :param default: 进行取值中报错时所返回的默认值 (default: None)
    :return: 返回根据参数locators找出的值
    '''
    # 如果接口响应数据非字典且定位取值器非列表，则直接返回默认值None
    if not isinstance(dic, dict) or not isinstance(locators, list):
        return default

    value = None

    for locator in locators:
        # 如果value非字典、列表，且定位器是不能转化为整数的字符串
        if not type(value) in [dict, list] and isinstance(locator, str) and not can_convert_to_int(locator):
            try:
                # 从返回值取出定位器对应的值
                value = dic[locator]
            except KeyError:
                return default
            continue
        # 如果取出的值是字典，则根据定位器继续取值
        if isinstance(value, dict):
            try:
                value = dict_get(value, [locator])
            except KeyError:
                return default
            continue
        if isinstance(value, list) and can_convert_to_int(locator):
            try:
                value = value[int(locator)]
            except IndexError:
                return default
            continue
    return value


def can_convert_to_int(input):
    try:
        int(input)
        return True
    except BaseException:
        return False
if __name__ == '__main__':
    # 示例用法
    json_data = '''
    {
        "name": "John",
        "age": 30,
        "city": "New York",
        "grades": {
            "math": [[0,1],[1,2]],
            "science": 85,
            "history": 88
        }
    }
    '''

    key_to_extract = [{"a":"$.grades.math[0][0]"},{"b":"$.grades.math[1][2]"}]
    result = extract_and_store_values(json_data, key_to_extract)
    print("提取的值为:", GLOBAL_VALS)

    # 示例用法

#     request_data = {
#         "name": "$name",
#         "age": "$age",
#         "location": {
#             "city": "$city",
#             "country": "$country"
#         },
#         "friends": [
#             {
#                 "name": "$friend1",
#                 "age": "$friend1_age"
#             },
#             {
#                 "name": "$friend2",
#                 "age": "$friend2_age"
#             }
#         ]
#     }
# #
#     GLOBAL_VALS = {
#         "name": "Alice",
#         "age": 25,
#         "city": "New York",
#         "country": "USA",
#         "friend1": "Bob",
#         "friend1_age": 30,
#         "friend2": "Charlie",
#         "friend2_age": 35
#     }
# result = substitution_variables(request_data)
# print(result)


